package com.srwl.mytx.im;

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.srwl.mytx.Constant;
import com.srwl.mytx.EaseConstant;
import com.srwl.mytx.dao.DBManager;
import com.srwl.mytx.domain.AliOssService;
import com.srwl.mytx.domain.Message;
import com.srwl.mytx.greendao.DaoSession;
import com.srwl.mytx.greendao.MessageDao;
import com.srwl.mytx.parse.UserProfileManager;
import com.srwl.mytx.utils.EaseNotifier;

import java.util.List;


public class MessageHandlerImpl implements MessageHandler {
    private static final String TAG = "MessageHandlerImpl";
    private Context context;
    private MessageDao messageDao;
    private MessageStateChangeListener stateChangeListener;
    //发送方用户Id
    private String fromId;
    private LocalBroadcastManager broadcastManager;
    private EaseNotifier notifier;
    private Handler handler = new Handler(Looper.getMainLooper());


    public MessageHandlerImpl(Context context, MessageStateChangeListener stateChangeListener) {
        this.context = context;
        this.stateChangeListener = stateChangeListener;
        messageDao = DBManager.getInstance().getDaoSession().getMessageDao();
        fromId = UserProfileManager.getInstance().getUserID();
        broadcastManager = LocalBroadcastManager.getInstance(context);
        notifier = new EaseNotifier(context);
    }


    @Override
    public void sendMessage(Message message) {

        //保存到本地
        saveMessage(message);
        //消息一开始发送，即使是文件类型消息，在没有上传之前，也应该保存进消息发送集合，
        // 只有这样，文件类型消息上传失败的时候，才能回显到聊天界面上
        if (stateChangeListener != null) {
            stateChangeListener.onMessageSend(message);
        }
        switch (message.getSubType()) {
            case Constant.IM_TYPE_TEXT:
            case Constant.IM_TYPE_COUPON:
            case Constant.IM_TYPE_TRANSFER:
            case Constant.IM_TYPE_GEO:
            case Constant.IM_TYPE_MESSAGE_READ_ACK:
                cloneAndSendMessage(message);
                break;
            case Constant.IM_TYPE_IMAGE:
                //判断是否是 转发消息，如果是直接发送
                if (TextUtils.isEmpty(message.getLocalFilePath()) && !TextUtils.isEmpty(message.getContent())) {
                    cloneAndSendMessage(message);
                    return;
                }
                //如果文件已经上传成功了的，直接发送
                if (checkFileUpLoadSuccess(message)) {
                    cloneAndSendMessage(message);
                    return;
                }
                //上传文件，设置消息为文件上传中
                message.setUploadState(Constant.MESSAGE_UPLOAD_STATE_UPLOADING);
                //消息id 作为 该条消息对应的文件的 key(名字)
                AliOssService.getInstance().uploadImImage(message.getId(), message.getLocalFilePath(), getListener(message));
                break;
            case Constant.IM_TYPE_AUDIO:
                if (TextUtils.isEmpty(message.getLocalFilePath()) && !TextUtils.isEmpty(message.getContent())) {
                    cloneAndSendMessage(message);
                    return;
                }
                if (checkFileUpLoadSuccess(message)) {
                    cloneAndSendMessage(message);
                    return;
                }
                //上传中
                message.setUploadState(Constant.MESSAGE_UPLOAD_STATE_UPLOADING);
                //消息id 作为 该条消息对应的文件的 key(名字)
                AliOssService.getInstance().uploadImAudio(message.getId(), message.getLocalFilePath(), getListener(message));
                break;

            case Constant.IM_TYPE_VIDEO:
                if (TextUtils.isEmpty(message.getLocalFilePath()) && !TextUtils.isEmpty(message.getContent())) {
                    cloneAndSendMessage(message);
                    return;
                }
                if (checkFileUpLoadSuccess(message)) {
                    cloneAndSendMessage(message);
                    return;
                }
                //上传中
                message.setUploadState(Constant.MESSAGE_UPLOAD_STATE_UPLOADING);
                //消息id 作为 该条消息对应的文件的 key(名字)
                AliOssService.getInstance().uploadImVideo(message.getId(), message.getLocalFilePath(), getListener(message));
                break;
        }
    }

    /**
     * 检查文件类型消息的 文件上传状态
     * 检测是否是一条文件上传成功，但是发送失败的消息
     *
     * @param message
     * @return
     */
    private boolean checkFileUpLoadSuccess(Message message) {
        Integer uploadState = message.getUploadState();
        if (uploadState != null) {
            //如果消息已经上传文件成功了的，无须重复上传,直接发送，
            // 这种情況是 文件上传成功，但是消息发送失败的，消息重发
            return uploadState.equals(Constant.MESSAGE_UPLOAD_STATE_SUCCESS);
        }
        return false;
    }

    @NonNull
    private AliOssService.OssListener getListener(Message message) {
        return new AliOssService.OssListener() {
            @Override
            public void onProgressChange(int progress) {
                //通过广播的形式 通知 消息上传进度改变
                Intent intent = new Intent(EaseConstant.ACTION_SEND_MESSAGE_PROGRESS_CHANGE);
                intent.putExtra(EaseConstant.UPLOAD_MSG_ID, message.getId());
                intent.putExtra(EaseConstant.UPLOAD_PROGRESS, progress);
                broadcastManager.sendBroadcast(intent);
            }

            @Override
            public void onSuccess(String fileKey) {
                message.setSendState(Constant.MESSAGE_UPLOAD_STATE_SUCCESS);
                message.setContent(fileKey);
                //文件上传成功后，把携带了文件 key 的消息发动给对方
                cloneAndSendMessage(message);
                updateMessage(message);
            }

            @Override
            public void onFailure(String errorCode, String content) {
                //文件上传失败，直接以发送失败处理，用户可以重新发送
                Log.e(TAG, "onFailure: 文件上传失败" + message.toString());
                if (stateChangeListener != null) {
                    handler.post(() -> stateChangeListener.onMessageSendFail(message));

                }
            }
        };
    }

    /**
     * 复制消息，并清空无须传给对方的属性
     */
    private void cloneAndSendMessage(Message message) {
        try {
            Message sendMessage = (Message) message.clone();
            //清空对消息接收方来说无用的属性，
            sendMessage.setcId(null);
            sendMessage.setSendState(null);
            sendMessage.setLocalFilePath(null);
            sendMessage.setPreviewUrl(null);
            sendMessage.setDownloadState(null);
            sendMessage.setUploadState(null);
            sendMessageToRemote(sendMessage);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
//        sendMessage.setId(message.getId());
//        sendMessage.setToId(message.getToId());
//        sendMessage.setFromId(message.getFromId());
//        sendMessage.setType(message.getType());
//        sendMessage.setVisible(Constant.MESSAGE_VISIBLE);
//      //  sendMessage.setReadState(Constant.MESSAGE_READ_STATE_UNREAD); 远程发送的消息不用设置读取状态，消息在收到的时候会设置为未读状态
//        sendMessage.setCreated(message.getCreated());
    }

    /**
     * 用原消息改造一条消息已读回执，清空内容，改变消息类型，
     * 消息id不变，这样对方收到，才能根据id 判断是哪条消息已读
     *
     * @param message
     */

    @Override
    public void sendMessageReadAck(Message message) {
        cloneAndSendMessage(message);
    }


    private void sendMessageToRemote(Message message) {
        MessageProcessor.getInstance().sendMsg(message);

    }


    @Override
    public void saveMessage(Message message) {
        try {
            messageDao.insertOrReplace(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateMessage(Message message) {
        try {
            messageDao.update(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setLocalMessageRead(String messageId) {
        try {
            DaoSession session = DBManager.getInstance().getDaoSession();
            String strSql = "update message set READ_STATE = " + Constant.MESSAGE_READ_STATE_READ + " where ID =" + messageId;
            session.getDatabase().execSQL(strSql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setMessageReadByConversationId(String conversationId) {
        try {
            DaoSession session = DBManager.getInstance().getDaoSession();
            String strSql = "update message set READ_STATE = " + Constant.MESSAGE_READ_STATE_READ + " where C_ID =" + conversationId;
            session.getDatabase().execSQL(strSql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setMessageSendState(Message message) {
        Log.i(TAG, "setMessageSendState: 更新消息发送状态：SendState" + message.getSendState());
        DaoSession session = DBManager.getInstance().getDaoSession();
        String strSql = "update message set SEND_STATE = " + message.getSendState() + " where ID =" + message.getId();
        session.getDatabase().execSQL(strSql);
    }

    @Override
    public void saveMessage(List<Message> messages) {
        try {
            messageDao.insertOrReplaceInTx(messages);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean deleteMessage(Message message) {
        try {
            messageDao.delete(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public void deleteMessage(String messageId) {
        try {
            messageDao.deleteByKey(messageId);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public boolean deleteMessage(List<Message> messages) {
        try {
            messageDao.deleteInTx(messages);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean deleteAllMessage(String conversationId) {
        try {
            DaoSession session = DBManager.getInstance().getDaoSession();
            String strSql = "delete from message  where C_ID ='" + conversationId + "'";
            session.getDatabase().execSQL(strSql);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    @Override
    public int queryMessageSizeByConversationId(String conversationId) {
        return (int) messageDao.queryBuilder().where(MessageDao.Properties.CId.eq(conversationId)).count();

    }

    @Override
    public List<Message> loadMoreMessage(int offset, int size, String conversationId) {
//        if (offset == 0) {
//        }
        messageDao.detachAll();
        //根据会话id读取一定数量的消息 (目前会话id 和聊天对象id 是相同的)，排除消息已读回执
        return messageDao.queryBuilder().where(MessageDao.Properties.CId.eq(conversationId)).orderDesc(MessageDao.Properties.Created).offset(offset).limit(size).list();
        // return messageDao.queryBuilder().where(MessageDao.Properties.CId.eq(conversationId)).where(MessageDao.Properties.Type.notEq(Constant.IM_TYPE_MESSAGE_READ_ACK)).orderDesc(MessageDao.Properties.Created).offset(offset).limit(size).list();

    }

    @Override
    public Message loadLastMessage(String conversationId) {
        try {
            List<Message> list = messageDao.queryBuilder().where(MessageDao.Properties.CId.eq(conversationId)).orderDesc(MessageDao.Properties.Created).limit(1).list();
            if (list != null && list.size() > 0) {
                return list.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Message> loadSentFailOrSendingMessageList() {
        return messageDao.queryBuilder().whereOr(MessageDao.Properties.SendState.eq(Constant.IM_SEND_STATE_FAIL), MessageDao.Properties.SendState.eq(Constant.IM_SEND_STATE_SENDING)).list();
    }

    @Override
    public void vibrateAndPlayTone() {
        notifier.vibrateAndPlayTone();
    }

    @Override
    public int queryUnreadCount(String conversationId) {
        return (int) messageDao.queryBuilder()
                .where(MessageDao.Properties.CId.eq(conversationId))
                .where(MessageDao.Properties.ReadState.eq(Constant.MESSAGE_READ_STATE_UNREAD))
                .count();
    }


    public void setStateChangeListener(MessageStateChangeListener stateChangeListener) {
        this.stateChangeListener = stateChangeListener;
    }

    public interface MessageStateChangeListener {

        void onMessageSendFail(Message message);

        //消息发送完成，但是并不代表成功，有可能在多次发送尝试之后，发送失败
        void onMessageSend(Message message);

        void onMessageSendSuccess(Message message);
    }
}
